#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>

#define NANOPERSEC 1000000000
#define NANOPERMSEC 1000000
#define MICROPERSEC 1000000
#define MICROPERMILLI 1000
#define MILLIPERSEC 1000

#define ERROR_RATE "error_rate: divide by zero"

long get_milli_time(){
    struct timeval time;
    gettimeofday(&time, NULL);
    return (time.tv_sec * MICROPERSEC + time.tv_usec) / MICROPERMILLI;
}

// Prints the time up to nanosecond precision
// Not followed by a newline
// Note that the nanosecond time currently decreases...
struct timeval print_time()
{
    int size = 30;
    char str_time[size];
    struct timeval time;
    struct tm* full_time;

    gettimeofday(&time, NULL);
    //clock_gett(time(CLOCK_REALTIME, &time);
    full_time = localtime(&time.tv_sec);

    strftime(str_time, size, "[%m:%d]%I:%M:%S.", full_time);
    printf("%s%d", str_time, (int)time.tv_usec);
    return time;
}

// Prints the time up to nanosecond precision
// Not followed by a newline
// Note that the nanosecond time currently decreases...
struct timeval get_time()
{
  //int size = 30;
    //char str_time[size];
    struct timeval time;
    struct tm* full_time;

    gettimeofday(&time, NULL);
    //clock_gett(time(CLOCK_REALTIME, &time);
    full_time = localtime(&time.tv_sec);

    //strftime(str_time, size, "[%m:%d]%I:%M:%S.", full_time);
    //printf("%s%d", str_time, (int)time.tv_usec);
    return time;
}


void calculate_rate(int pkt_per_sec, struct timespec * period)
{
    if (pkt_per_sec == 0)
    {
        perror(ERROR_RATE);
        exit(1);
    }

    else if(pkt_per_sec == 1)
    {
	period->tv_sec = 1;
        period->tv_nsec = 0;
	printf("WAIT PERIOD (ns): %ld\n", period->tv_sec * NANOPERSEC);
    }
    else
    {
	period->tv_sec = 0;
        period->tv_nsec = NANOPERSEC / pkt_per_sec ;

	printf("WAIT PERIOD (ns): %ld\n", period->tv_nsec);
    }

    // Use nanosleep(*period, NULL); to wait necessary amount of time between sends of sequential packets
}

long calculate_rate_milli(int pkt_per_sec)
{
    if (pkt_per_sec == 0)
    {
        perror(ERROR_RATE);
        exit(1);
    }

    else if(pkt_per_sec == 1)
    {
	return MILLIPERSEC;
    }
    else
    {
        return MILLIPERSEC / pkt_per_sec;
    }
}

// Seed the random number generator
void init_rand()
{
    srand(time(NULL));
}

// Based off of a whole number percentage (of true)
// Returns 1 for true
// Returns 0 for false
int bool_rand(int percent_true)
{
    int random = rand();

    random = random % 100;  // will generate value 0 - 100
    if (random < percent_true)
    {
        return 1; // TRUE
    }
    else
    {
        return 0; // FALSE
    }
}

// Sleep for msec_period (milliseconds); note that this can be greater
// than one second
void delay(int msec_period)
{
    struct timespec delay_spec;
    delay_spec.tv_sec = msec_period/1000;
    delay_spec.tv_nsec = msec_period%1000 * NANOPERMSEC;
    nanosleep(&delay_spec, NULL);
}
